package algo3.algothief.modelo;

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;

import javax.xml.parsers.ParserConfigurationException;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.xml.sax.SAXException;


public class Policia {
	
	private Pais paisActual;
	
	private RangoPolicia rangoActual;
	
	private DescripcionDeLadron descripcionDelSospechoso;
	
//-------------------------------------------------------------------------------------	
	
	public Policia(RangoPolicia rangoInicial) {
		this.paisActual = null;
		
		this.rangoActual = rangoInicial;
		
		this.descripcionDelSospechoso = new DescripcionDeLadron();
	}
	
//-------------------------------------------------------------------------------------	
	
	public Element serializar(Document doc) {
		Element elementoPolicia = doc.createElement("Policia");
		
		Element elementoPais = this.serializarPais(doc);
		Element elementoRango = rangoActual.serializar(doc, "Actual");
		Element elementoDescripcion = descripcionDelSospechoso.serializar(doc, "-hecha-por-el-policia");
		
		elementoPolicia.appendChild(elementoPais);
		elementoPolicia.appendChild(elementoRango);
		elementoPolicia.appendChild(elementoDescripcion);
					
		return elementoPolicia;
	}
		
	public static Policia hidratar(Document doc, ArrayList<Pais> paisesDelMundo) throws ParserConfigurationException, SAXException, IOException {
		Element elementoPolicia = (Element)doc.getElementsByTagName("Policia").item(0);
		
		Pais paisActual = Policia.hidratarPais(elementoPolicia, paisesDelMundo);
		RangoPolicia rangoActual = RangoPolicia.hidratar(doc, "Actual");
		DescripcionDeLadron descripcionDelSospechoso = DescripcionDeLadron.hidratar(doc, "-hecha-por-el-policia");
		
		Policia policiaNuevo = new Policia(rangoActual);
		policiaNuevo.modificarPaisActual(paisActual);
		policiaNuevo.definirDescripcionDelSospechoso(descripcionDelSospechoso);
		
		return policiaNuevo;
	}
	
//-------------------------------------------------------------------------------------	

	private Element serializarPais(Document doc) {
		Element elementoPais = doc.createElement("PaisDondeEstaElPolicia");
		if (this.paisActual == null )
			elementoPais.setAttribute("nombreDeLaCapital", "");
		else
			elementoPais.setAttribute("nombreDeLaCapital", paisActual.verNombreDeLaCapital());
		
		return elementoPais;
	}
	
	
	
	private static int buscarIndiceEnPaisesDelPais(ArrayList<Pais> paises, String nombreDelPais) {
		int indiceDelPais = -1;
		int cantidadDePaises = paises.size();
		
		for (int i = 0; ( (indiceDelPais == -1) && (i < cantidadDePaises) ); i++) {
			String nombreDelPaisActual = paises.get(i).verNombreDeLaCapital();
			
			if (nombreDelPaisActual.matches(nombreDelPais)) 
				indiceDelPais = i;
		}
		
		return indiceDelPais;
	}
	
	private static Pais hidratarPais(Element elementoPolicia, ArrayList<Pais> paises) {
		Element elementoPais = (Element)elementoPolicia.getElementsByTagName("PaisDondeEstaElPolicia").item(0);
		String nombreDeLaCapital = elementoPais.getAttribute("nombreDeLaCapital");
		
		if (nombreDeLaCapital.matches("")) 
			return null;
		
		int indiceDelPaisDelMismoNombre = Policia.buscarIndiceEnPaisesDelPais(paises, nombreDeLaCapital);
		Pais pais = paises.get(indiceDelPaisDelMismoNombre);
		
		return pais;
	}
	
	private void definirDescripcionDelSospechoso(DescripcionDeLadron descripcion) {
		this.descripcionDelSospechoso = descripcion;
	}
	
//-------------------------------------------------------------------------------------
	
	public RangoPolicia verRango() {
		return this.rangoActual;
	}
	
	public double verVelocidadDeViaje() {
		return rangoActual.verVelocidadDeViaje(); // En km por hora
	}
	
	
	public Pais verPaisDondeEsta() {
		return this.paisActual;
	}
	
	public void modificarPaisActual(Pais pais) {
		this.paisActual = pais;
	}
	
	
	public void asignarUnCaso(Caso caso) {
		Pais paisInicialDelCaso = caso.verElPaisInicialDelCaso();
		this.modificarPaisActual(paisInicialDelCaso);
	}
	
	
	public DescripcionDeLadron verLaDescripcionDelSospechosoHechaPorElPolicia() {
		return this.descripcionDelSospechoso;
	}
	
	public HashMap<String,ArrayList<String>> verOpcionesPosiblesParaLaDescripcionDelSospechoso() {
		HashMap<String,ArrayList<String>> opcionesPosibles = new HashMap<String,ArrayList<String>>();
		
		opcionesPosibles.put("sexos posibles", descripcionDelSospechoso.verSexosPosibles());
		opcionesPosibles.put("hobbys posibles", descripcionDelSospechoso.verHobbysPosibles());
		opcionesPosibles.put("cabellos posibles", descripcionDelSospechoso.verCabellosPosibles());
		opcionesPosibles.put("senias posibles", descripcionDelSospechoso.verSeniasPosibles());
		opcionesPosibles.put("vehiculos posibles", descripcionDelSospechoso.verVehiculosPosibles());
		
		return opcionesPosibles;
	}
	
	public void modificarDescripcionDelSospechoso(HashMap<String,String> elecciones) {
		descripcionDelSospechoso.seleccionarUnSexo(elecciones.get("Sexo"));
		descripcionDelSospechoso.seleccionarUnHobby(elecciones.get("Hobby"));
		descripcionDelSospechoso.seleccionarUnCabello(elecciones.get("Cabello"));
		descripcionDelSospechoso.seleccionarUnaSenia(elecciones.get("Senia"));
		descripcionDelSospechoso.seleccionarUnVehiculo(elecciones.get("Vehiculo"));
	}
	
	
	public int emitirOrdenDeArresto(CuartelGeneral cuartelGeneral) {
		int horasTranscurridasPorEmitirLaOrden = cuartelGeneral.emitirOrdenDeArresto(descripcionDelSospechoso);
		return horasTranscurridasPorEmitirLaOrden;
	}
	
	
	
	public String obtenerElRango() {
		return rangoActual.verNombre();
	}
	
	public int verLaCantidadDeArrestosActual() {
		return rangoActual.verCantidadDeArrestosActual();
	}
	
	public void incrementarCantidadDeArrestos(int incremento) {
		this.rangoActual = rangoActual.intentarPromoverElRango(incremento);
	}
	
	public int verCuantosArrestosFaltanParaLaProximaPromocion() {
		return rangoActual.verCuantosArrestosFaltanParaPromocion();
	}
	
	
	
	public ObjetoRobado definirObjetoQueSeRobaraSegunElRango() {
		ObjetoRobado objetoRobado = rangoActual.definirObjetoQueSeRobara();
		return objetoRobado;
	}
}
